<?php

class Core_Data_UDD_Structure {

    private $DocumentCollection;
    private $DatabaseCollection;

    function __construct () {
        $this->DocumentCollection = new ArrayObject ();
        $this->DatabaseCollection = new ArrayObject ();
    }

    /**
     * Outputs an HTML document detailing the structure.
     *
     * @param string $strHTML Used to store the HTML instead of outputting it.
     */
    public function info ( &$strHTML = null ) {

        $objHTML = new Core_Presentation_HTML_Docuement ();
        $objHTML->Title = "Core_Data_UDD_Structure::info()";

        $strHTML = "";
        $strHTML .= "<h1>Core_Data_UDD_Structure::info()</h1>";
        $strHTML .= "<h2>Documents</h2>";
        $strHTML .= "<tr><th>Filename</th><th>Project Name</th><th>Project Version</th><th>Revision</th></tr>";
        $strHTML .= "<table>";

        foreach ( $this->documents() as $objDocument ) {
            $strHTML .= "<tr>";
            $strHTML .= "<td>" . $objDocument->getFilename() . "</td>";
            $strHTML .= "<td>" . $objDocument->getProjectName() . "</td>";
            $strHTML .= "</tr>";
        }

        $strHTML .= "</table>";
        $strHTML .= "<h2>Structure</h2>";

        foreach ( $this->databases() as $objDatabase ) {

        }

        $objHTML->importHTML( $strHTML );

        echo $objHTML->getHTML();

    }

    /**
     * Interprets a Universal Database Definition document.
     *
     * @param string $strFilename
     */
    public function interpretDocument ( $strFilename ) {
        // The actual interpreting of the document goes on here.
        // We assume that the document is valid, even though no schema is used yet.

        $xmlUDD = simplexml_load_file( $strFilename );

        $objDocument = $this->addDocument( $strFilename );
        $strVersion = $xmlUDD->attributes()->version; // Not used for anything yet.

        $objDocument->setProjectName( $xmlUDD->ProjectName[0] );
        $objDocument->setProjectName( $xmlUDD->ProjectVersion[0] );
        $objDocument->setRevision( $xmlUDD->Revision[0] );

        foreach ( $xmlUDD->Database as $xmlDatabase ) {

            $strDatabaseName = ( $xmlDatabase->attributes()->Name ) ? $xmlDatabase->attributes()->Name : "__default";

            if ( in_array( $strDatabaseName, $this->databases() ) ) {
                $objDatabase = $this->databases()->__default;
            } else {
                $objDatabase = $this->addDatabase( $strDatabaseName );
            }

            foreach ( $xmlDatabase->Table as $xmlTable ) {

                $strTableName = $xmlTable->attributes()->Name;
                $strTablePrefix = ( isset( $xmlTable->attributes()->Prefix ) ) ? $xmlTable->attributes()->Prefix : null;

                // TODO: Throw an exception if the table already exists.

                $objTable = $objDatabase->addTable( $objDocument, $strTableName, $strTablePrefix );

                if ( isset( $xmlTable->attributes()->extends ) ) {
                    // TODO: Throw an exception if the table doesn't exist.
                    // NOTE: The parent table must already be added for this to work.
                    // NOTE: This requires parent tables to exist in the same database.
                    $strParent = $xmlTable->attributes()->extends;
                    $objTable->setParent( $objDatabase->tables()->$strParent );
                }

                foreach ( $xmlTable->Field as $xmlField ) {

                    $strName = $xmlField->attributes()->Name;
                    $strDataType = ( isset( $xmlField->attributes()->DataType ) ) ? $xmlField->attributes()->DataType : Core_Data_UDD_DataTypes::TEXT;

                    $objField = $objTable->addField( $strName, $strDataType );

                    if ( $xmlField->attributes()->key == "true" ) {
                        switch ( $xmlField->attributes()->keytype ) {
                            case "parent":
                                $objField->setKey( Core_Data_UDD::KEY_PARENT );
                                break;
                            case "unique":
                            default:
                                $objField->setKey( Core_Data_UDD::KEY_UNIQUE );
                                break;
                        }
                    }

                    if ( $xmlField->attributes()->required == "true" ) {
                        $objField->setRequired();
                    }

                }

                // TODO: Walk through methods and add record as well.

            }

        }

    }

    /**
     * Creates and appends a new Universal Database Definition document.
     *
     * @param string $strFilename
     */
    public function addDocument ( $strFilename ) {
        $objDocument = new Core_Data_UDD_Structure_Document ( $strFilename );
        $this->DocumentCollection[] = $objDocument;
        return $objDocument;
    }

    /**
     * Creates and appends a new database.
     *
     * @param string $strName
     * @return Core_Data_UDD_Structure_Database
     */
    public function addDatabase ( $strName ) {
        $objDatabase = new Core_Data_UDD_Structure_Database ( $strName );
        $this->DatabaseCollection[$objDatabase] = $objDatabase;
        return $objDatabase;
    }

    /**
     * Gets the databases.
     *
     * @return ArrayObject
     */
    public function databases () {
        return $this->DatabaseCollection;
    }

    /**
     * Gets the documents.
     *
     * @return ArrayObject
     */
    public function documents () {
        return $this->DocumentCollection;
    }

    /**
     * Saves the structure into Universal Database Definition documents.
     */
    public function save () {
        // To be written later.
    }

}

?>
